home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Light ROM 3
/
Light ROM 3 - Disc 2.iso
/
programs
/
pc
/
vp2raw
/
vp2raw.c
next >
Wrap
C/C++ Source or Header
|
1993-01-12
|
19KB
|
647 lines
/***************************************************************************/
/* */
/* VP2RAW.C Viewpoint to Raw triangle converter */
/* */
/* Takes the 3 numbers following the delimiter v, stores */
/* them in an array, then reads the connection table and */
/* generates a polygon data file that's converted into */
/* triangles */
/* */
/* Written to get Viewpoint files into anything else. */
/* */
/* Jeff Bowermaster & Steve Anger */
/* Splat! Graphics */
/* 1/11/93 */
/* */
/* Syntax: VP2RAW filename.ext [outfile] */
/* */
/* Input: A Viewpoint object file */
/* */
/* g */
/* v 3.660927 0.002173 -0.738231 */
/* v 3.719482 0.346536 -0.832918 */
/* v ... */
/* */
/* Output: filename.RAW (or a specified filename) */
/* */
/* in the form: */
/* */
/* texture */
/* vx1 vy1 vz1 vx2 vy2 vz2 vx3 vy3 vz3 */
/* vx1 vy1 vz1 vx2 vy2 vz2 vx3 vy3 vz3 */
/* vx1 vy1 vz1 vx2 vy2 vz2 vx3 vy3 vz3 */
/* vx1 vy1 vz1 vx2 vy2 vz2 vx3 vy3 vz3 */
/* ... */
/* */
/* Some cluze: */
/* */
/* vn 0.332949 -0.705421 0.625720 */
/* vn -0.260047 -0.789584 0.555817 */
/* vn 0.532304 -0.547688 0.645515 */
/* vn -0.440163 0.835449 -0.329062 */
/* */
/* vn Viewpoint files can contain vn (vertex normal) information, and */
/* based on the fact that there are usually more vertex normals than */
/* vertex's (vertii?) I assume they are normal to the center of the */
/* polygon, but I get really vague about the reason. I don't use them. */
/* */
/* Folowing the vn's, there is a connection table in the form: */
/* */
/* g coat */
/* s 1 */
/* f 66//52 67//53 68//54 69//55 */
/* f 69//55 68//54 70//56 71//57 */
/* f 71//57 70//56 72//58 73//59 */
/* f 73//59 72//58 74//60 75//61 */
/* f 75//61 74//60 76//62 77//63 */
/* f 77//63 76//62 78//64 79//65 */
/* f 79//65 78//64 80//66 81//67 */
/* ... */
/* */
/* g I parse the name (coat) and define a texture block with the color */
/* gray. Go in and edit these textures to whatever you like. */
/* */
/* s May be a smoothing group. I just ignore it too. */
/* */
/* f The first number (before the //) is the vertex, the second number */
/* is the normal. Lines denote individual polygons, thus these are */
/* all squares. I've seen 13gons (tridecagons), but they are generally */
/* 3-4-5 gons. */
/* */
/* Some Viewpoint files do not contain vertex normals so the connection */
/* table can be used directly. I'm also leaving that one up to you. */
/* */
/* Thank you Viewpoint for allowing these files to be distributed so */
/* freely. Awfully decent of you people. */
/* */
/***************************************************************************/
#include <math.h>
#include <string.h>
#include <alloc.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
float x, y, z;
}
Vector;
int remove_triangle (Vector *poly, int *polysize, Vector *v1, Vector *v2,
Vector *v3);
int poly_inside (Vector *poly, int polysize, Vector *v);
void vect_init (Vector *v, float x, float y, float z);
void vect_copy (Vector *v1, Vector *v2);
void vect_add (Vector *v1, Vector *v2, Vector *v3);
void vect_sub (Vector *v1, Vector *v2, Vector *v3);
void vect_scale (Vector *v, float k);
float vect_mag (Vector *v);
float dot_prod (Vector *v1, Vector *v2);
void cross_prod (Vector *v1, Vector *v2, Vector *v3);
float vect_angle (Vector *v1, Vector *v2);
void add_ext (char *fname, char *ext, int force);
int polyread (int argc, char *argv[]);
void main(int argc, char *argv[])
{
char *ptr, *infile, *outfile, *string, buffer[5];
char parse0, parse1,*texture,tex[50][20];
FILE *in, *out;
int a,count,i,n,t,textures,x,done,length,pos,point1,point2,vertexnum[15],have;
Vector vertex;
Vector huge *coords = NULL;
Vector huge *keep;
printf("(V)iew(P)oint 2 (RAW) Triangle Translator\n");
printf(" (c) 1993 Jeff Bowermaster & Steve Anger,\n Splat! Graphics\n");
if (argc < 2)
{
printf("\nUsage: VP2RAW filename[.obj] [outfile]\n");
printf(" outfile defaults to filename.raw\n");
exit(1);
}
string=(char *)malloc(256);
texture=(char *)malloc(80);
infile=(char *)calloc(80,sizeof(char));
outfile=(char *)calloc(80,sizeof(char));
strcpy (infile, argv[1]);
if (argc > 2)
strcpy (outfile, argv[2]);
else {
strcpy (outfile, infile);
add_ext (outfile, "pol", 1);
}
add_ext (infile, "obj", 1);
add_ext (outfile, "pol", 0);
if ((in = fopen (infile, "r")) == NULL) {
printf ("Cannot open input file %s!\n", infile);
exit (1);
}
if((out = fopen(outfile,"wt"))==NULL) {
printf ("Cannot open output file %s!\n", outfile);
exit (1);
}
printf("\nReading %s for vertex count...\n",argv[1]);
count=0;
n=0;
while (fgets(string,256,in) != NULL) { // get a line
parse0 = string[0];
parse1 = string[1];
switch (parse0) {
case 'v':
// v 3.660927 0.002173 -0.738231
if(parse1==' ') {
count++;
}
break;
case 'g':
/* g skin */
if(parse1==' ') {
sscanf(string,"%*s %s",texture);
have=0;
for(x=0;x<n;x++)
if(!strcmp(texture,tex[x])) have=1;
if(!have)
strcpy(tex[n++],texture);
}
break;
default: /* Blank lines, page numbers... */
break;
}
}
for(x=0;x<n;x++) {
for(a=0;a<strlen(tex[x]);a++) {
if(tex[x][a]==' ') tex[x][a] = '_';
}
printf(" %d %s\n",x,tex[x]);
}
if ((coords = farmalloc ((long)count * sizeof(Vector)))==NULL) {
printf("Insufficient memory for vertices.\n");
exit(1);
}
else
printf("Allocating memory for %d vertices.\n",count);
keep=coords;
printf("Writing data to %s. Please wait...\n",outfile);
textures=n;
for(t=0;t<textures;t++) {
printf("Working on %s\n",tex[t]);
fprintf(out,"%s\n",tex[t]);
rewind(in);
while (fgets(string,256,in) != NULL) { // get a line
parse0 = string[0];
parse1 = string[1];
switch (parse0) {
case 'v':
// v 3.660927 0.002173 -0.738231
if(parse1==' ' && !t) {
sscanf(string,"%*s %f %f %f\n",
&vertex.x,&vertex.y,&vertex.z);
coords->x=vertex.x;
coords->y=vertex.y;
coords->z=vertex.z;
coords++;
// fprintf(out,"%f %f %f\n",vertex.x,vertex.y,vertex.z);
}
break;
case 'g':
/* g skin */
sscanf(string,"%*s %s\n",texture);
if(strcmp(tex[t],texture))
break;
break;
case 'f':
/* f 2576//2175 2732//2331 2721//2320
1) get the numbers before the //
2) save the first one
3) repeat it at the end of the line
*/
if(strcmp(tex[t],texture))
break;
coords=keep;
length=strlen(string);
buffer[0]='\0';
buffer[1]='\0';
buffer[2]='\0';
buffer[3]='\0';
buffer[4]='\0';
pos = 0;
n = 0;
for(x=2;x<length;x++){
switch (string[x]) {
case '/':
vertexnum[n++]=atoi(buffer);
buffer[0]='\0';
buffer[1]='\0';
buffer[2]='\0';
buffer[3]='\0';
buffer[4]='\0';
pos=0;
while(string[x++]!=' ');
x--;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
buffer[pos++]=string[x];
break;
default:
break;
}
}
fprintf(out,"%d ",n);
for(i=0;i<n;i++)
fprintf(out,"%f %f %f ",
(coords+vertexnum[i]-1)->x,
(coords+vertexnum[i]-1)->y,
(coords+vertexnum[i]-1)->z);
fprintf(out,"\n");
break;
default: /* Blank lines, page numbers... */
break;
}
}
}
fclose(in);
fclose(out);
polyread(argc,argv);
}
/*----------------------------------------------------------------------
Polygon to triangle converter
by Steve Anger Jan 1993
This program is commited to the public domain. Feel free to use all or part
of this code in your own programs.
This is a utility that breaks polygon shapes down into individual
triangles. The polygons are assumed to be planar however the program
should be able to tolerate slightly non-planar shapes.
The input file consists of one line per polygon in the following format:
n x1 y1 z1 x2 y2 z2 ..... xn yn zn
where n is the number of vertices in the polygon and xi, yi, and zi are the
coordinates of the polygon's vertices.
The output file consists of one triangle per line in the following format:
x1 y1 z1 x2 y2 z2 x3 y3 z3
-----------------------------------------------------------------------*/
#define POLYMAX 17
#define BUFSIZ 512
int polyread (int argc, char *argv[])
{
FILE *f, *g;
Vector poly[POLYMAX], v1, v2, v3;
int polysize, cnt, i, j, start;
char infile[80] = "", outfile[80] = "",parse,*string,texture[20];
if (argc < 2) {
printf ("Usage: infile[.pol] [outfile[.raw]]\n");
exit(1);
}
string=malloc(BUFSIZ);
strcpy (infile, argv[1]);
if (argc > 2)
strcpy (outfile, argv[2]);
else {
strcpy (outfile, infile);
add_ext (outfile, "raw", 1);
}
add_ext (infile, "pol", 1);
add_ext (outfile, "raw", 0);
f = fopen (infile, "r");
if (f == NULL) {
printf ("Unable to open input file '%s'\n", infile);
exit(1);
}
g = fopen (outfile, "w");
if (g == NULL) {
printf ("Unable to open output file '%s'\n", outfile);
exit(1);
}
printf("Converting polygons to triangles...\n");
cnt = 0;
while (fgets(string,BUFSIZ,f) != NULL) { // get a line
parse = string[0];
switch (parse) {
case '\x0A':
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
polysize = 0;
start=1;
sscanf (string, "%d", &polysize);
if (polysize > POLYMAX) {
printf ("Polygon %d too large (%d), skipping.\n",cnt,polysize);
fgets(string,BUFSIZ,f); //read to the end of this one
break;
}
if(polysize>9)
start=2;
for (i=0;i<polysize; i++) {
sscanf (&string[start], "%f %f %f", &poly[i].x, &poly[i].y, &poly[i].z);
for(j=0;j<3;j++){
start=strchr(&string[start+1],' ')-string;
}
}
/* Remove triangles from the polygon until there's nothing left */
while (remove_triangle (poly, &polysize, &v1, &v2, &v3)) {
fprintf (g, "%f %f %f %f %f %f %f %f %f \n",
v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z);
}
cnt++;
if (cnt % 10 == 0)
printf ("%d\r", cnt);
break;
default:
sscanf(string,"%s",&texture);
fprintf(g,"%s\n",texture);
break;
}
}
fclose (f);
fclose (g);
return (0);
}
/* Removes a triangle from the specified polygon. */
/* The size of the polygon is reduced */
int remove_triangle (Vector *poly, int *polysize,Vector *v1, Vector *v2, Vector *v3)
{
Vector tri[3], center;
int i, j, a, b, c;
if (*polysize < 3)
return 0; /* No triangle found */
/* This simplest case */
if (*polysize == 3) {
vect_copy (v1, &poly[0]);
vect_copy (v2, &poly[1]);
vect_copy (v3, &poly[2]);
*polysize = 0;
return 1; /* Ok */
}
for (i = 0; i < *polysize; i++) {
a = i;
b = (i + 1) % *polysize;
c = (i + 2) % *polysize;
/* Select a candidate triangle */
vect_copy (&tri[0], &poly[a]);
vect_copy (&tri[1], &poly[b]);
vect_copy (&tri[2], &poly[c]);
/* Calculate the center of the triangle */
vect_init (¢er, 0.0, 0.0, 0.0);
vect_add (¢er, ¢er, &tri[0]);
vect_add (¢er, ¢er, &tri[1]);
vect_add (¢er, ¢er, &tri[2]);
vect_scale (¢er, 1.0/3.0);
/* Is the center of the triangle inside the original polygon? */
/* If not skip this triangle */
if (!poly_inside (poly, *polysize, ¢er))
continue;
/* Are any of the polygons other vertices inside the triangle */
/* If so skip this triangle */
for (j = 0; j < *polysize; j++) {
if (j != a && j != b && j != c && poly_inside (tri, 3, &poly[j]))
break;
}
if (j < *polysize)
continue;
/* This is the one */
vect_copy (v1, &tri[0]);
vect_copy (v2, &tri[1]);
vect_copy (v3, &tri[2]);
/* Remove this triangle from the polygon */
(*polysize)--;
for (j = b; j < *polysize; j++)
vect_copy (&poly[j], &poly[j+1]);
return 1; /* Ok */
}
return 0; /* No triangle found */
}
/* Determines if the specified point 'v' is inside the polygon. */
/* Uses a convoluted version of the sum of angles approach */
int poly_inside (Vector *poly, int polysize, Vector *v)
{
Vector sum, cross, v1, v2;
float magcross;
int i;
vect_init (&sum, 0.0, 0.0, 0.0);
for (i = 0; i < polysize; i++) {
vect_sub (&v1, v, &poly[i]);
vect_sub (&v2, v, &poly[(i+1) % polysize]);
cross_prod (&cross, &v1, &v2);
magcross = vect_mag (&cross);
if (magcross > 0.0)
vect_scale (&cross, 1.0/magcross);
vect_scale (&cross, vect_angle (&v1, &v2));
vect_add (&sum, &sum, &cross);
}
return (vect_mag (&sum) > M_PI);
}
void vect_init (Vector *v, float x, float y, float z)
{
v->x = x;
v->y = y;
v->z = z;
}
void vect_copy (Vector *v1, Vector *v2)
{
v1->x = v2->x;
v1->y = v2->y;
v1->z = v2->z;
}
void vect_add (Vector *v1, Vector *v2, Vector *v3)
{
v1->x = v2->x + v3->x;
v1->y = v2->y + v3->y;
v1->z = v2->z + v3->z;
}
void vect_sub (Vector *v1, Vector *v2, Vector *v3)
{
v1->x = v2->x - v3->x;
v1->y = v2->y - v3->y;
v1->z = v2->z - v3->z;
}
void vect_scale (Vector *v, float k)
{
v->x = k * v->x;
v->y = k * v->y;
v->z = k * v->z;
}
float vect_mag (Vector *v)
{
float mag = sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
return mag;
}
float dot_prod (Vector *v1, Vector *v2)
{
return (v1->x*v2->x + v1->y*v2->y + v1->z*v2->z);
}
void cross_prod (Vector *v1, Vector *v2, Vector *v3)
{
v1->x = (v2->y * v3->z) - (v2->z * v3->y);
v1->y = (v2->z * v3->x) - (v2->x * v3->z);
v1->z = (v2->x * v3->y) - (v2->y * v3->x);
}
/* Return the angle (rads) between two vectors */
float vect_angle (Vector *v1, Vector *v2)
{
float mag1, mag2, angle, cos_theta;
mag1 = vect_mag(v1);
mag2 = vect_mag(v2);
if (mag1 * mag2 == 0.0)
angle = 0.0;
else {
cos_theta = dot_prod(v1,v2) / (mag1 * mag2);
if (cos_theta <= -1.0)
angle = M_PI;
else if (cos_theta >= +1.0)
angle = 0.0;
else
angle = acos(cos_theta);
}
return angle;
}
void add_ext (char *fname, char *ext, int force)
{
int i;
for (i = 0; i < strlen(fname); i++)
if (fname[i] == '.') break;
if (fname[i] == '\0' || force) {
if (strlen(ext) > 0)
fname[i++] = '.';
strcpy (&fname[i], ext);
}
}